package fun.zhufn.oldcomm.model.bo.json;

import java.io.File;
import java.io.FileOutputStream;

/**
 * Json格式错误
 */
class BadJsonException extends RuntimeException {
}

/**
 * Json解析和编码
 */
public class MyJsonParser {

    /** 写入文件
     * @param path 路径
     * @param data Json数据
     * @throws Exception 文件写入异常
     */
    public static void writeToFile(String path, Object data) throws Exception {
        File f = new File(path);
        try (FileOutputStream fs = new FileOutputStream(f)) {
            fs.write(gen(data).getBytes());
        }
    }

    /** 解析json
     * @param json json字符串
     * @return 对应的数据，可能为HashMap&lt;String, Object&gt;, ArrayList&lt;Object&gt;, String, boolean, int, double类型
     * @throws BadJsonException json格式错误
     */
    public static Object parse(String json) throws BadJsonException {
        json = json.trim();
        if (json.startsWith("[") && json.endsWith("]")) {
            JsonList ret = new JsonList();
            json = json.substring(1, json.length() - 1);
            while (true) {
                int p1 = 0, p2 = findNextComma(json), len = json.length();
                String curLine = json.substring(p1, p2).trim();
                if (curLine.isEmpty()) break;
                ret.add(parse(curLine));

                if (p2 < len) json = json.substring(p2 + 1);
                else break;
            }
            return ret;
        } else if (json.startsWith("{") && json.endsWith("}")) {
            return nextObject(json);
        } else if (json.startsWith("\"") && json.endsWith("\"")) {
            int cnt = 0;
            for (int i = 0; i < json.length(); ++i) {
                if (json.charAt(i) == '"' && (i > 0 && json.charAt(i - 1) != '\\')) {
                    ++cnt;
                }
            }
            if (cnt > 2) throw new BadJsonException();
            return json.substring(1, json.length() - 1);
        } else if (json.equals("true")) {
            return true;
        } else if (json.equals("false")) {
            return false;
        } else if (json.equals("null")) {
            return null;
        } else {
            try {
                return Integer.parseInt(json);
            } catch (Exception e) {
                try {
                    return Double.parseDouble(json);
                } catch (Exception e2) {
                    throw new BadJsonException();
                }
            }
        }
    }

    private static JsonMap nextObject(String json) throws BadJsonException {
        JsonMap ret = new JsonMap();
        if (!json.startsWith("{") || !json.endsWith("}")) {
            throw new BadJsonException();
        }
        json = json.substring(1, json.length() - 1).trim();
        if (json.isEmpty()) return ret;
        while (true) {
            int p1 = 0, p2 = findNextComma(json), len = json.length();
            String curLine = json.substring(p1, p2).trim();
            if (curLine.startsWith("\"")) {
                int j = stringPos(curLine);
                String key = curLine.substring(1, j);
                curLine = curLine.substring(j + 1).trim();
                if (!curLine.startsWith(":")) throw new BadJsonException();
                ret.put(key, parse(curLine.substring(1).trim()));
            } else {
                throw new BadJsonException();
            }
            if (p2 < len) json = json.substring(p2 + 1);
            else break;
        }
        return ret;
    }

    private static int stringPos(String str) throws BadJsonException {
        if (!str.startsWith("\"")) {
            throw new BadJsonException();
        }
        int i = 1;
        while (i < str.length()) {
            if (str.charAt(i) == '"') {
                break;
            }
            ++i;
        }
        if (i == str.length()) throw new BadJsonException();
        return i;
    }

    private static int findNextComma(String json) throws BadJsonException {
        int quoteCnt = 0, squareBracketsCnt = 0, bracesCnt = 0;
        int len = json.length();
        int i = 0;
        while (i < len) {
            if (json.charAt(i) == ',' && quoteCnt % 2 == 0 && squareBracketsCnt == 0 && bracesCnt == 0) {
                break;
            }
            if (json.charAt(i) == '"') {
                ++quoteCnt;
            }
            if (json.charAt(i) == '[') {
                ++squareBracketsCnt;
            }
            if (json.charAt(i) == '{') {
                ++bracesCnt;
            }
            if (json.charAt(i) == ']') {
                --squareBracketsCnt;
            }
            if (json.charAt(i) == '}') {
                --bracesCnt;
            }
            ++i;
        }
        return i;
    }

    /** 生成json
     * @param data 转json的数据，除HashMap&lt;String, Object&gt;, ArrayList&lt;Object&gt;, String, boolean, int, double之外的类型会被toString()并成为字符串
     * @return json字符串
     */
    public static String gen(Object data) {
        if (data instanceof JsonMap mp) {
            StringBuilder ret = new StringBuilder("{");
            for (String key : mp.keySet()) {
                ret.append("\"").append(key).append("\":");
                ret.append(gen(mp.get(key)));
                ret.append(",");
            }
            if (ret.charAt(ret.length() - 1) == ',') ret.delete(ret.length() - 1, ret.length());
            ret.append("}");
            return ret.toString();
        } else if (data instanceof JsonList) {
            StringBuilder ret = new StringBuilder("[");
            for (Object v : (JsonList) data) {
                ret.append(gen(v));
                ret.append(",");
            }
            if (ret.charAt(ret.length() - 1) == ',') ret.delete(ret.length() - 1, ret.length());
            ret.append("]");
            return ret.toString();
        } else if (data instanceof String) {
            return "\"" + data + "\"";
        } else if (data == null) {
            return "null";
        } else {
            return data.toString();
        }
    }
}
